home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / program / progem.arc / gem5.asc < prev    next >
Text File  |  1987-10-10  |  17KB  |  335 lines

  1.                         *PROFESSIONAL GEM*
  2.                 Part 5 -- Resource Tree Structures
  3.                            By Tim Oren
  4.  
  5.      This is the fifth issue of ST PROFESSIONAL GEM, concluding our
  6. trek through GEM dialogs and resources with a look at the internal
  7. structure of object trees.  Also, I'll answer a number of questions
  8. of general interest which have been received via the ANTIC ONLINE
  9. FEEDBACK.  As always, there is a download file associated with this
  10. column: GEMCL5.C, which you will find in DL3 of the new Atari 16-bit
  11. SIG (type GO PCS-58 or GO ATARI16).
  12.  
  13.      Even if you have no immediate use for this issue's code, be sure
  14. to take the download anyway; some of the routines will be used in
  15. later articles.
  16.  
  17.      In the last installment, we established that resources trees are
  18. pointed to by the tree index, and that they are composed of objects
  19. which contain pointers onward to other structures.  However, we
  20. passed over the issue of linkage among the objects within a tree.  It
  21. is now time to go back and cure this omission.
  22.  
  23.      The technical term for the linkage scheme of an object tree is a
  24. "right-threaded binary tree".   If you already know what this is, you
  25. can skim over the next few paragraphs.  If you happen to have access
  26. to a copy of the book "FUNDAMENTAL ALGORITHMS", which is part of the
  27. series THE ART OF COMPUTER PROGRAMMING by Donald E. Knuth, you might
  28. want to read his excellent discussion of binary trees beginning on
  29. page 332.
  30.  
  31.      For the following discussion, you should have a listing of the C
  32. image of a resource tree in front of you.  For those who do not have
  33. the listing from the last column, I have included a fragment at the
  34. beginning of the download.  Before we begin, I should warn you of one
  35. peculiarity of "computer trees":  They grow upside-down!  That is,
  36. when they are diagrammed or described, their root is at the top, and
  37. the  "leaves" grow downward.  You will see this both in the listing,
  38. and in the way the following discussion talks about moving through
  39. trees.
  40.  
  41.      Each GEM object tree begins at its ROOT object, numbered zero,
  42. which is the object pointed at by the tree index.  There are three
  43. link  fields at the beginning of each object.  They are called
  44. OB_NEXT, OB_HEAD,  and OB_TAIL, which is the order in which they
  45. appear.
  46.  
  47.      Each of the links is shown as an index relative to the root of
  48. the current tree.  This means that the link '0' would refer to the
  49. root of the tree, while '2' would indicate the object two lines below
  50. it. The special link -1 is called NIL, and means that there is no
  51. link in  the given direction.
  52.  
  53.      Each object, or node, in a tree may have "offspring" or nodes
  54. which are nested below it.  If it does, then its OB_HEAD will point
  55. to its first (or "leftmost") "child", while the OB_TAIL will point to
  56. the last ("rightmost") of its offspring.  The OB_NEXT pointer links
  57. the  children together, with the OB_NEXT of the first pointing to the
  58. second, and so on, until the OB_NEXT of the last finally points back
  59. to its parent, the object at which we started.
  60.  
  61.      Remember that each of these children may in turn have offspring
  62. of their own, so that the original "parent" may have a large and
  63. complex collection of "descendents".
  64.  
  65.      Let's look at the first tree in the download to see an example
  66. of this structure.  The very first object is the ROOT.  Note that its
  67. OB_NEXT is NIL, meaning that there are no more objects in the tree:
  68. the ROOT is both the beginning and the end of the tree.  In this
  69. case, the OB_HEAD is 1 and the OB_TAIL is 3, showing that there are
  70. at least two different children.
  71.  
  72.      Following OB_HEAD down to the next line, we can trace through
  73. the OB_NEXT links (2, 3, 0) as they lead through a total of three
  74. children and back to the ROOT.  You will notice that the first two
  75. children have NIL for the OB_HEAD and OB_TAILs, indicating that they
  76. have no further offspring.
  77.  
  78.      However, node three, the last child of the ROOT, does have the
  79. value 4 for both its OB_HEAD and OB_TAIL.  By this we can tell that
  80. it  has one, and only one, offspring.  Sure enough, when we look at
  81. node four, we see that its OB_NEXT leads immediately back to node
  82. three. Additionally, it has no further offspring because its OB_HEAD
  83. and OB_TAIL are NIL.
  84.  
  85.      You will find that object trees are always written out by the
  86. Resource Construction Set in "pre-order".  (Again, see Knuth if you
  87. have a copy.)  This means that the ROOT is always written first, then
  88. its offspring left to right.  This rule is applied recursively, that
  89. is, we go down to the next level and write out each of these nodes,
  90. then THEIR children left to right, and so on.
  91.  
  92.      For a further example, look at the next tree in rs_object in the
  93. download.  You will see that the ROOT has an OB_HEAD of 1 and an
  94. OB_TAIL of 6, but that it actually has only three offspring (nodes 1,
  95. 2 and 6).  We see that node 2 itself had children, and applying the
  96. rule given above, they were written out before continuing with the
  97. next child of the ROOT.
  98.  
  99.      Why was this seemingly complex structure chosen for GEM?  The
  100. reason has do with the tasks of drawing objects in their proper
  101. locations on the screen, and determining which object was "hit" when
  102. a mouse click is detected.
  103.  
  104.      To find out how this works, we must look at four more fields
  105. found in each object: OB_X, OB_Y, OB_WIDTH, and OB_HEIGHT.  These
  106. fields are the last four on each line in the sample trees.
  107.  
  108.      Each object in a tree "owns" a rectangle on the screen.  These
  109. fields define that rectangle.  When a resource is stored "outside"
  110. the  program the fields are in character units, so that an object
  111. with OB_WIDTH  of 10 and OB_HEIGHT of 2 (for instance) would define a
  112. screen area 10  characters wide and 2 high.
  113.  
  114.      When the resource is read into memory with an rsrc_load call,
  115. GEM multiplies the appropriate character dimension in pixels into
  116. each of these fields.  In this way portability is achieved: the same
  117. resource file works for any of the ST's three resolutions.  Knowing
  118. how rsrc_load works, your code should treat these fields as pixel
  119. coordinates.
  120.  
  121.      (I have committed one oversimplification above.  If an object is
  122. not created on a character boundary in the RCS, then the external
  123. storage method described will not work.  In this case, the lower byte
  124. of each rectangle field is used to store the nearest character
  125. position, while the upper byte stores the pixel remainder to be added
  126. after the character size is multiplied in.
  127.  
  128.      Non-character-boundary objects may only be created in the "FREE"
  129. tree mode of the Resource Construction Set (also called "PANEL" in
  130. RCS 2.0). You should use them only in programs which will run in a
  131. single ST screen  mode, because pixel coordinates are not portable
  132. between resolutions.)
  133.  
  134.      The first real secret of object rectangles is that each OB_X and
  135. OB_Y is specified RELATIVE to the X and Y coordinate of its parent
  136. object  within the tree.  This is the first property we have seen
  137. that is actually "inherited" from level to level within the tree.
  138.  
  139.      The second secret is more subtle:  Every object's rectangle must
  140. be entirely contained within the rectangle of its parent.  This
  141. principle goes by the names "bounding rectangles" or "visual
  142. hierarchy".  We'll see in a moment how useful it is when detecting
  143. mouse/object collisions.
  144.  
  145.                          HOW GEM DOES IT.
  146.  
  147.      Knowing these secrets, and the linkage structure  of object
  148. trees, we can deduce how a number of the GEM operations must work.
  149. For instance, consider objc_offset,  which returns the actual screen
  150. X and Y  of an object.  We can see now that simply loading the OB_X
  151. and OB_Y fields of  the object does not suffice: they only give the
  152. offset relative to the parent  object.  So, objc_offset must BEGIN
  153. with these values, and then work its way  back up to the ROOT of the
  154. tree, adding in the offsets found at each level.
  155.  
  156.      This can be done by following the OB_NEXT links from the chosen
  157. object.  Whenever OB_NEXT points to an object whose OB_TAIL points
  158. right back  to the same location, then the new node is another level,
  159. or "parent" in the  tree, and objc_offset adds its OB_X and OB_Y into
  160. the ru